package com.stock.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stock.constant.StockConstant;
import com.stock.dao.IStockDao;
import com.stock.dao.IStockDayDao;
import com.stock.dto.StockResponseDto;
import com.stock.entity.StockDayEntity;
import com.stock.entity.StockEntity;
import com.stock.enums.StockEnum;
import com.stock.service.IStockService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class StockService extends ServiceImpl<IStockDao, StockEntity> implements IStockService {

    private final IStockDayDao stockDayDao;

    private final RedisTemplate redisTemplate;

    public StockService(IStockDayDao stockDayDao, RedisTemplate redisTemplate) {
        this.stockDayDao = stockDayDao;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void saveDataZT(String beginDate) {
        commonSave(beginDate, StockConstant.TO_DAY_LIMIT_UP);
    }

    @Override
    public void saveDataAll(String beginDate) {
        commonSave(beginDate, StockConstant.STRONG_STOCK_POOL);
    }

    public void commonSave(String beginDate, String type) {
        DateTime dateTime = DateUtil.parse(beginDate);
        LambdaUpdateWrapper<StockEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(StockEntity::getCreatedTime, dateTime);
        this.remove(lambdaUpdateWrapper);
        String url = type + beginDate;
        String s = HttpUtil.get(url);
        String substring = s.substring(s.indexOf("{"), s.length() - 2);
        StockResponseDto stockRespnseDto = JSONUtil.toBean(substring, StockResponseDto.class);
        StockResponseDto.StockTemp stockTemp = stockRespnseDto.getData().get(0);
        List<StockEntity> list = Convert.toList(StockEntity.class, stockTemp.getPool());
        list.stream().forEach(stockEntity -> {
            stockEntity.setCreatedTime(dateTime);
            stockEntity.setUpdatedTime(dateTime);
        });
        this.saveBatch(list);
    }

    /**
     * 获取日数据
     * @param type
     * @return
     */
    @Override
    public List<StockDayEntity> getStockDayData(Integer type) {
        Date maxDate = Convert.toDate(redisTemplate.opsForValue().get("maxDate"));
        // 如果 maxDate 不存在，则查询数据库并更新缓存
        if (maxDate == null) {
            maxDate = stockDayDao.getMaxDate();
            redisTemplate.opsForValue().set("maxDate", maxDate);
        }
        String formattedDate = DateUtil.format(maxDate, "yyyy-MM-dd");
        return this.getStockData(type, formattedDate);
    }

    /**
     *
     * @param type
     * @param today
     * @return
     */
    private List<StockDayEntity> getStockData(Integer type, String today) {
        String cacheKey = "stockDayData:" + today + ":type:" + type;
        // 先查询 Redis 是否有缓存
        List<StockDayEntity> cachedData = (List<StockDayEntity>) redisTemplate.opsForValue().get(cacheKey);
        if (CollUtil.isNotEmpty(cachedData)) {
            return cachedData;
        }
        // Redis 没有缓存，查询数据库
        QueryWrapper<StockDayEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("date", today)
                .eq("is_del", 0)
                .orderByDesc("rate");

        List<StockDayEntity> list = stockDayDao.selectList(wrapper);
        if (CollUtil.isEmpty(list)) {
            redisTemplate.opsForValue().set(cacheKey, Collections.emptyList(), 86400, TimeUnit.SECONDS);
            return Collections.emptyList();
        }
        // 根据 type 进行筛选
        List<StockDayEntity> filteredList = this.filterStocksByType(list, type);
        // 将结果存入 Redis 缓存，并设置缓存过期时间
        redisTemplate.opsForValue().set(cacheKey, filteredList, 86400, TimeUnit.SECONDS);
        return filteredList;
    }

    /**
     *
     * @param stocks
     * @param type
     * @return
     */
    private List<StockDayEntity> filterStocksByType(List<StockDayEntity> stocks, Integer type) {
        if (ObjectUtil.equal(type, StockEnum.GEM.getCode())) {
            return stocks.stream()
                    .filter(stock -> stock.getCode() != null && stock.getCode().startsWith("30"))
                    .collect(Collectors.toList());
        } else if (ObjectUtil.equal(type, StockEnum.MAIN_BOARD.getCode())) {
            return stocks.stream()
                    .filter(stock -> stock.getCode() != null && !stock.getCode().startsWith("30"))
                    .collect(Collectors.toList());
        } else {
            return stocks;
        }
    }

    /**
     * 获取昨日数据
     * @param type
     * @return
     */
    @Override
    public List<StockDayEntity> getStockYesterdayData(Integer type) {
        Date oldMaxDate = Convert.toDate(redisTemplate.opsForValue().get("oldMaxDate"));
        // 如果 maxDate 不存在，则查询数据库并更新缓存
        if (oldMaxDate == null) {
            Date maxDate = stockDayDao.getMaxDate();
            oldMaxDate = stockDayDao.getOldMaxDate(DateUtil.format(maxDate,"yyyy-MM-dd"));
            redisTemplate.opsForValue().set("oldMaxDate", oldMaxDate);
        }
        // 计算昨天的日期并格式化
        String formattedDate = DateUtil.format(oldMaxDate, "yyyy-MM-dd");
        return this.getStockData(type, formattedDate);
    }

}
